const THREE =qguan("three")

const ThreeReact = {};
const ReactDOM = {};
class Component {
    constructor(props){
        this.props = props;
    }
    setState(partialState,cb){
        batchUpdater.stateQueue.push(partialState);
        cb && batchUpdater.cbQueue.push(cb);
        batchUpdater.dirtyComponents.push(this);
    }
    updateComponent(allState){
        Object.assign(this.state, allState);
        const new_element = this.render();
        const { _inner_element } = this;
        const patches = compareElement(new_element, _inner_element);
        if(patches.length){
            applyPatches(patches);
        }else{
            //no diff
            return ;
        }
    }
}
ThreeReact.Component = Component;
//return object
ThreeReact.createElement = function(type,props,...children){
    props = props || {};
    props.children = arguments.length === 3 ? children[0] : children;
    const {key = null,...other} = props; //最新版的chrome已经支持这个语法了，但是babel居然要 transform-object-rest-spread 才能支持
    return {
        type,
        props:other,
        key,
        _inst:null,
        _inner_element:null,
        _dom:null,
        _renderOne:null
    }
}

const batchUpdater = {
    isUpdating:false,
    stateQueue:[],
    cbQueue:[],
    dirtyComponents:[],
    open(){
        batchUpdater.isUpdating = false;
    },
    close(){
        batchUpdater.isUpdating = true;
        var allState = batchUpdater.stateQueue.reduce((prev,state)=>{
            return Object.assign(prev,state);
        });
        batchUpdater.dirtyComponents.forEach(comp=>{
            comp.updateComponent(allState)
        });
        batchUpdater.cbQueue.forEach((fn,idx)=>{
            fn.call(batchUpdater.dirtyComponents[idx]);
        });
    },
    wrapper:function(fn){
        return function(e){
            batchUpdater.open();
            fn(e);
            batchUpdater.close();
        }
    }
}


function setDomStyleProps(dom, style){
    Object.assign(dom.style, style);
    if( typeof style.width === 'number'){
        dom.style.width = style.width + 'px';
    }
}

//渲染一个组件，输入虚拟dom，输出真实dom
function renderOne(element){
    var dom
    if(typeof element === 'string' || typeof element === 'number'){
        dom = document.createTextNode(element);
    }else if(typeof element === 'object'){
        if(typeof element.type === 'string'){
            const { props } = element;
            if(props.style){
                dom = new THREE[element.type](...props.style) ;
            }else {
                dom = new THREE[element.type]() ;
            }
            if(element.id) dom.id = element.id;
            if(element.key) dom.key = element.key;


            props.type && dom.setAttribute('type',props.type);
            props.checked &&  dom.setAttribute('checked',!!props.checked);
            if(props.onClick){
                //react中是使用合成事件的，鉴于时间问题先省略
                dom.addEventListener('click',batchUpdater.wrapper(props.onClick));
            }
            if(typeof props.children !== 'undefined'){
                if(props.children.forEach){
                    props.children.forEach(child=>render(child, dom));
                } else{
                    render(props.children, dom);
                }
            }
            element._dom = dom;
            element._renderOne = renderOne;
        }else if(typeof element.type === 'function'){
            const inst = new element.type(element.props);
            const inner_element = inst.render();
            dom = renderOne(inner_element);
            inst._inner_element = inner_element;
            // element._inst = inst;
            inst._dom = dom;
            inst._renderOne = renderOne;
        }else {
            const inst = Object.assign({}, element.type);
            inst.props=element.props;
            const inner_element = inst.render();
            dom = renderOne(inner_element);
            inst._inner_element = inner_element;
            // element._inst = inst;
            inst._dom = dom;
            inst._renderOne = renderOne;
        }
    }
    return dom;
}
var  camera;
var renderer;
var scene;
//把dom挂载到上级目录里面
function render(element,mountNode ){
    mountNode.add(renderOne(element))
    threeRenderer( );
}
//渲染
function threeRenderer() {
    requestAnimationFrame(threeRenderer);
    renderer.render(scene,  camera);
}
//把一个虚拟dom挂载到一个真实dom里面
function renderRoot(element,mountNode ,renderers,cameras,scenes){
    // mountNode.appendChild(renderOne(element));
    //初始化渲染器
    if(element.renderers){
        renderer=element.renderers;
    }else {
        renderer = new THREE.webGLRenderer();
        // renderer.setClearColor('white');//设置渲染出来的背景色
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize(window.innerWidth,window.innerHeight);
    }

    mountNode.appendChild(renderer.domElement);

    //初始化摄像头
    if(element.cameras){
        camera=element.cameras;
    }else {
        camera = new THREE.perspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
        camera.position.set(10, 10, 800);
    }
    //初始化场景
    if(element.scenes){
        scene=element.scenes
    }else {
        scene = new THREE.scene();
        scene.background = new THREE.color(0xf0f0f0);　//背景

        let light = new THREE.ambientLight(0xfefefe); //光线
        scene.add(light);
        scene.add( new THREE.pointLightHelper( light, 15 ) );
        /*
            4、添加辅助坐标轴
        */
        var axes = new THREE.axisHelper(800);
        scene.add(axes);
        /*
                   5、添加地面网格
               */
        /**
         * size 网格总边长
         * step 网格个数
         * colorCenterLine  网格中心线颜色
         * colorGrid    网格其他线颜色
         */
        var gridHelper = new THREE.gridHelper( 300, 10, 'red', 'gray' );
        gridHelper.position.y = -100;
        gridHelper.position.x = 0;
        scene.add( gridHelper );
    }



    // threeRenderer();
   render(element,scene);
}

ThreeReact.render = renderRoot;

export default ThreeReact;